﻿using System;
using System.Windows.Forms;
using YougeBookmark.Models;
using System.ComponentModel;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace YougeBookmark.Services
{
    /// <summary>
    /// 剪贴板交互服务（线程安全实现）
    /// 功能说明：
    /// 1. 安全获取剪贴板文本内容
    /// 2. URL格式验证与自动修正
    /// 3. 剪贴板占用异常处理
    /// </summary>
    public static class ClipboardService
    {
        private static readonly object _syncRoot = new object();
        private static readonly string[] _urlSchemes = { "http://", "https://", "ftp://" };

        /// <summary>
        /// 尝试从剪贴板获取有效URL（支持重试机制）
        /// </summary>
        /// <param name="maxRetries">最大重试次数（默认3次）</param>
        /// <param name="retryDelay">重试间隔（毫秒，默认100ms）</param>
        /// <returns>
        /// Item1: 是否成功获取有效URL
        /// Item2: 验证通过的URL（失败时为null）
        /// </returns>
        /// <exception cref="Win32Exception">剪贴板访问权限错误时抛出</exception>
        public static (bool success, string url) TryGetUrl(int maxRetries = 3, int retryDelay = 100)
        {
            lock (_syncRoot)
            {
                for (int i = 0; i < maxRetries; i++)
                {
                    try
                    {
                        if (Clipboard.ContainsText())
                        {
                            var rawText = Clipboard.GetText(TextDataFormat.Text);
                            var formattedUrl = FormatUrlCandidate(rawText);

                            if (Bookmark.IsValidUrl(formattedUrl))
                                return (true, formattedUrl);
                        }
                        return (false, null);
                    }
                    catch (ExternalException ex) when (IsClipboardBusy(ex))
                    {
                        // 剪贴板被占用时等待重试
                        Thread.Sleep(retryDelay);
                    }
                    catch (Exception ex) when (IsNonCriticalException(ex))
                    {
                        Debug.WriteLine($"剪贴板访问失败: {ex.Message}");
                        return (false, null);
                    }
                }
                throw new Win32Exception("无法访问剪贴板，可能被其他程序占用");
            }
        }

        /// <summary>
        /// 智能格式化候选URL（自动修正常见问题）
        /// </summary>
        private static string FormatUrlCandidate(string input)
        {
            if (string.IsNullOrWhiteSpace(input)) return null;

            var trimmed = input.Trim();

            // 处理带引号的URL（常见于邮件客户端）
            if (trimmed.StartsWith("\"") && trimmed.EndsWith("\""))
                trimmed = trimmed.Substring(1, trimmed.Length - 2);

            // 自动补充协议前缀
            if (!HasScheme(trimmed))
                trimmed = "http://" + trimmed;

            return trimmed;
        }

        /// <summary>
        /// 检查是否包含协议头
        /// </summary>
        private static bool HasScheme(string url)
        {
            foreach (var scheme in _urlSchemes)
            {
                if (url.StartsWith(scheme, StringComparison.OrdinalIgnoreCase))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 判断是否为剪贴板繁忙异常
        /// </summary>
        private static bool IsClipboardBusy(ExternalException ex)
        {
            const int CLIPBRD_E_CANT_OPEN = unchecked((int)0x800401D0);
            const int CLIPBRD_E_CANT_CLOSE = unchecked((int)0x800401D1);

            return ex.ErrorCode == CLIPBRD_E_CANT_OPEN
                || ex.ErrorCode == CLIPBRD_E_CANT_CLOSE;
        }

        /// <summary>
        /// 过滤非关键性异常
        /// </summary>
        private static bool IsNonCriticalException(Exception ex)
        {
            return ex is ArgumentException
                || ex is InvalidOperationException;
        }

        /// <summary>
        /// 安全设置剪贴板内容（自动清除历史）
        /// </summary>
        public static void SafeSetText(string text)
        {
            lock (_syncRoot)
            {
                try
                {
                    Clipboard.Clear();  // 清除旧数据
                    Clipboard.SetText(text);
                }
                catch (Exception ex) when (IsNonCriticalException(ex))
                {
                    Debug.WriteLine($"剪贴板设置失败: {ex.Message}");
                }
            }
        }
    }
}